package edu.georgiasouthern.gui;

import java.applet.Applet;

import java.awt.TextField;

import edu.georgiasouthern.common.DataSet;
import edu.georgiasouthern.common.GisData;
import edu.georgiasouthern.common.GisDate;
import edu.georgiasouthern.common.DataSet.FileDelimiter;
import edu.georgiasouthern.common.GisDate.DateDomain;
import edu.georgiasouthern.common.LocationDataSet;
import edu.georgiasouthern.fileio.FileIO;
import edu.georgiasouthern.interpolation.ConcurrentInterpolationSec;
import edu.georgiasouthern.validation.LOOCV;
import edu.georgiasouthern.visualization.AnimTest;

import javax.swing.BoxLayout;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.awt.GridBagLayout;
import javax.swing.JTextField;
import javax.swing.JButton;
import javax.swing.JLabel;
import java.awt.FlowLayout;
import javax.swing.JTabbedPane;
import javax.swing.JToggleButton;
import java.awt.GridLayout;
import java.awt.GridBagConstraints;
import java.awt.Insets;
import javax.swing.JSplitPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JTextPane;
import javax.swing.JList;
import javax.swing.JRadioButton;
import javax.swing.WindowConstants;

import java.awt.Choice;
import javax.swing.JPopupMenu;
import java.awt.Component;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.ButtonGroup;
import javax.swing.JComboBox;

import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JScrollPane;
import javax.swing.ScrollPaneConstants;

import javax.swing.SwingUtilities;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableModel;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.DocumentFilter;

import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.InputStreamReader;

public class Gui extends Applet {
	public Gui() {
	}

	String FileFormat;
	GisDate.DateDomain DateFormat;
	JLabel lblDataFileName;
	JLabel lblInterFileName;
	DataSet dataSet;
	LocationDataSet locationDataSet;
	JTextPane txtDataSet;
	JTextPane txtLocationDataSet;
	JTable dsTable;
	JTable ldsTable;
	JLabel lblErrors;
	private JTextField fromMonth;
	private JTextField toMonth;
	public void init() {

		setSize(500, 500);
		setLayout(null);

		JPanel panel = new JPanel();
		panel.setBounds(0, 0, 500, 95);
		add(panel);
		panel.setLayout(null);

		JLabel lblNewLabel = new JLabel("Data File:");
		lblNewLabel.setBounds(10, 4, 71, 14);
		panel.add(lblNewLabel);

		JButton btnFileDialog = new JButton("...");
		btnFileDialog.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				File f = getFileName();
				if (f != null) {
					OpenFileOptions();
					System.out.println("File Format" + FileFormat);
					System.out.println("Date Format" + DateFormat);

					Gui.this.dataSet = new DataSet(f.getAbsolutePath(),
							DateFormat, DataSet.FileDelimiter
									.valueOf(FileFormat));
					if(Gui.this.dataSet.getDataCount()<1){
						Gui.this.dataSet = null;
						lblDataFileName.setText("No File Selected");
					}else{
						lblDataFileName.setText(f.getName());
						dsTable.setModel(TableDs());
						lblErrors.setText("");
					}

				}
			}
		});
		btnFileDialog.setBounds(255, 0, 38, 23);
		panel.add(btnFileDialog);

		lblDataFileName = new JLabel("No File Selected");
		lblDataFileName.setBounds(91, 4, 154, 14);
		panel.add(lblDataFileName);

		JLabel lblInterpolationFile = new JLabel("Location File");
		lblInterpolationFile.setBounds(10, 29, 71, 14);
		panel.add(lblInterpolationFile);

		lblInterFileName = new JLabel("No File Selected");
		lblInterFileName.setBounds(91, 29, 154, 14);
		panel.add(lblInterFileName);

		JButton button = new JButton("...");
		button.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {

				File f = getFileName();
				if (f != null) {
					
					OpenFileOptions();
					Gui.this.locationDataSet = new LocationDataSet(f
							.getAbsolutePath(), LocationDataSet.FileDelimiter
							.valueOf(FileFormat));
					if(Gui.this.locationDataSet.getData().size()<1){
						Gui.this.locationDataSet = null;	
						lblInterFileName.setText("No File Selected");
					}else{
						lblInterFileName.setText(f.getName());
					ldsTable.setModel(TableLds());
					}
				}
			}
		});
		button.setBounds(255, 25, 38, 23);
		panel.add(button);
		lblErrors = new JLabel("");
		lblErrors.setBounds(1,45,499,23);
panel.add(lblErrors);
		JButton btnInterpolate = new JButton("Interpolate!");
		btnInterpolate.setBounds(10, 67, 99, 23);
		btnInterpolate.addActionListener(new ActionListener(){

			@Override
			public void actionPerformed(ActionEvent e) {
			
				final JDialog dialog2 = new JDialog();
				dialog2.setBounds(0, 0, 300,300);
				dialog2.getContentPane().setLayout(new FlowLayout());
				if(locationDataSet==null|| dataSet==null){
					dialog2.getContentPane().add(new JLabel("You must select files first"));
					JButton jb = new JButton("OK");
					jb.addActionListener(new ActionListener() {
					
					@Override
					public void actionPerformed(ActionEvent e) {
					dialog2.setVisible(false);
						
					}
				});
					dialog2.getContentPane().add(jb);
					dialog2.setVisible(true);
				}else{
					dialog2.getContentPane().add(new JLabel("Please Enter the Exponent and Neighbors."));					
					// 
					JPanel pnlExpNei = new JPanel(new FlowLayout());
					pnlExpNei.setBounds(0,0,300,50);
					
					pnlExpNei.add(new JLabel("Exponent: "));
					final JTextField exp = new JTextField("1     ");
					pnlExpNei.add(exp);
					pnlExpNei.add(new JLabel("Neighbors: "));
					final JTextField neighbors = new JTextField("3     ");
					pnlExpNei.add(neighbors);
					dialog2.getContentPane().add(pnlExpNei);
					//
					
					
					dialog2.setResizable(false);
					dialog2.setModal(true);
					final JButton jb = new JButton("OK");
					jb.addActionListener(new ActionListener() {
					@Override
					public void actionPerformed(ActionEvent e) {
						final int neigh =Integer.parseInt(neighbors.getText().trim());
						final Float expon = Float.parseFloat(exp.getText().trim());
						Thread interThread = new Thread(new Runnable() {
						    public void run() {
						    	dialog2.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
						    	jb.setEnabled(false);
						       runInterpolate(dialog2,neigh,expon);
						    }}); 
						
						interThread.start();
						
					}
				});
					
					dialog2.getContentPane().add(jb);
					dialog2.getContentPane().add(new ConsoleWindow());
					dialog2.setVisible(true);
					

				}
				
			}
			
		});
	 
		panel.add(btnInterpolate);

		JButton btnfoldValidation = new JButton("LOOCV Validation");
		btnfoldValidation.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
			
				final JDialog dialog2 = new JDialog();
				dialog2.setBounds(0, 0, 300,300);
				dialog2.getContentPane().setLayout(new FlowLayout());
				if( dataSet==null){
					dialog2.getContentPane().add(new JLabel("You must select files first"));
					JButton jb = new JButton("OK");
					jb.addActionListener(new ActionListener() {
					
					@Override
					public void actionPerformed(ActionEvent e) {
					dialog2.setVisible(false);
						
					}
				});
					dialog2.getContentPane().add(jb);
					dialog2.setVisible(true);
				}else{
					dialog2.getContentPane().add(new JLabel("Please Enter the Exponent and Neighbors."));					
					// 
					JPanel pnlExpNei = new JPanel(new FlowLayout());
					pnlExpNei.setBounds(0,0,300,50);
					
					pnlExpNei.add(new JLabel("Exponent: "));
					final JTextField exp = new JTextField("1     ");
					pnlExpNei.add(exp);
					pnlExpNei.add(new JLabel("Neighbors: "));
					final JTextField neighbors = new JTextField("3     ");
					pnlExpNei.add(neighbors);
					dialog2.getContentPane().add(pnlExpNei);
					//
					
					
					dialog2.setResizable(false);
					dialog2.setModal(true);
					final JButton jb = new JButton("OK");
					jb.addActionListener(new ActionListener() {
					@Override
					public void actionPerformed(ActionEvent e) {
						final int neigh =Integer.parseInt(neighbors.getText().trim());
						final Float expon = Float.parseFloat(exp.getText().trim());
						Thread interThread = new Thread(new Runnable() {
						    public void run() {
						    	dialog2.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
						    	jb.setEnabled(false);
						       runValidate(dialog2,neigh,expon);
						    }}); 
						
						interThread.start();
						
					}
				});
					
					dialog2.getContentPane().add(jb);
					dialog2.getContentPane().add(new ConsoleWindow());
					dialog2.setVisible(true);
					

				}
				
			}
			
		});
			

		btnfoldValidation.setBounds(170, 67, 150, 23);
		panel.add(btnfoldValidation);
		
		JButton btnVisualization = new JButton("Visualization");
		btnVisualization.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
	
				AnimTest a = new AnimTest();
				JDialog dialog = new JDialog();
				dialog.setSize(1200,500);
				try {
					dialog.getContentPane().add(a.displayMap(new InputStreamReader(getClass().getResourceAsStream("/county_xy.txt")), new InputStreamReader(getClass().getResourceAsStream("/test3.txt"))));
				} catch (FileNotFoundException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
 		dialog.setVisible(true);
				
				
				
				
			}
		});
		btnVisualization.setBounds(353, 67, 123, 23);
		panel.add(btnVisualization);
		
		JLabel lblStartMonth = new JLabel("Month From");
		lblStartMonth.setBounds(303, 29, 71, 14);
		panel.add(lblStartMonth);
		
		fromMonth = new JTextField();
		fromMonth.setText("6");
		fromMonth.setBounds(376, 26, 37, 20);
		panel.add(fromMonth);
		fromMonth.setColumns(10);
		
		toMonth = new JTextField();
		toMonth.setText("8");
		toMonth.setBounds(452, 26, 38, 20);
		panel.add(toMonth);
		toMonth.setColumns(10);
		
		JLabel lblQueryInterpolation = new JLabel("Query Interpolation");
		lblQueryInterpolation.setBounds(330, 4, 131, 14);
		panel.add(lblQueryInterpolation);
		
		JLabel lblNewLabel_3 = new JLabel("to");
		lblNewLabel_3.setBounds(418, 29, 27, 14);
		panel.add(lblNewLabel_3);
		
				JPanel panel_1 = new JPanel();
				panel_1.setBounds(0, 96, 495, 400);
				add(panel_1);
				panel_1.setLayout(null);
				
						dsTable = new JTable(TableDs());
						dsTable.setBounds(-3, -2, 0, 393);
						panel_1.add(dsTable);
						
								ldsTable = new JTable(TableLds());
								ldsTable.setBounds(-3, -2, 0, 393);
								panel_1.add(ldsTable);
								
										JScrollPane scrollPane = new JScrollPane(dsTable);
										scrollPane.setBounds(0, 22, 240, 370);
										panel_1.add(scrollPane);
										scrollPane
												.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
										
												JScrollPane scrollPane_1 = new JScrollPane(ldsTable);
												scrollPane_1.setBounds(245, 22, 243, 373);
												panel_1.add(scrollPane_1);
												
														JLabel lblDataPane = new JLabel("Data Pane");
														lblDataPane.setBounds(0, 0, 129, 14);
														panel_1.add(lblDataPane);
														
																JLabel lblInterpolationPane = new JLabel("Interpolation Pane");
																lblInterpolationPane.setBounds(251, 0, 156, 14);
																panel_1.add(lblInterpolationPane);
		FileIO f = new FileIO();

	}

	private static void addPopup(Component component, final JPopupMenu popup) {
	}

	private TableModel TableDs() {
		TableModel dsDataModel = new AbstractTableModel() {
			public int getColumnCount() {
				return 4;
			}

			public int getRowCount() {
				if (dataSet != null && dataSet.getData() != null)
					return dataSet.getData().size();
				else
					return 0;
			}

			public Object getValueAt(int row, int col) {
				if (dataSet != null && dataSet.getData() != null) {
					switch (col) {
					case 0:
						return dataSet.getData().get(row).getX();
					case 1:
						return dataSet.getData().get(row).getY();
					case 2:
						return dataSet.getData().get(row).getDate();
					default:
						return dataSet.getData().get(row).getMeasurement();
					}
				} else
					return null;
			}
		};
		return dsDataModel;
	}

	private TableModel TableLds() {

		TableModel ldsDataModel = new AbstractTableModel() {
			public int getColumnCount() {
				return 4;
			}

			public int getRowCount() {
				if (locationDataSet != null
						&& locationDataSet.getData() != null)
					return locationDataSet.getData().size();
				else
					return 0;
			}

			public Object getValueAt(int row, int col) {
				if (locationDataSet != null
						&& locationDataSet.getData() != null) {
					switch (col) {
					case 0:
						return locationDataSet.getData().get(row).getX();
					case 1:
						return locationDataSet.getData().get(row).getY();
					case 2:
						return locationDataSet.getData().get(row).getDate();
					default:
						return locationDataSet.getData().get(row)
								.getMeasurement();
					}
				} else
					return null;
			}
		};
		return ldsDataModel;
	}

	private File getFileName() {
		JFileChooser fc = new JFileChooser();
		int val = fc.showOpenDialog(Gui.this);
		if (val == JFileChooser.APPROVE_OPTION) {
			return fc.getSelectedFile();
		} else
			return null;
	}

	private void OpenFileOptions() {
		final JDialog dialog = new JDialog(
				SwingUtilities.windowForComponent(this));
		dialog.setModal(true);
		dialog.getContentPane().setLayout(null);
		dialog.setSize(300, 200);
		JLabel lblNewLabel_2 = new JLabel("Please Select the file format.");
		lblNewLabel_2.setBounds(0, 0, 200, 14);
		dialog.getContentPane().add(lblNewLabel_2);
		JLabel lblNewLabel_1 = new JLabel("Date Format");
		lblNewLabel_1.setBounds(10, 23, 75, 14);
		dialog.getContentPane().add(lblNewLabel_1);

		JComboBox cmbDate = new JComboBox(GisDate.DateDomain.values());
		cmbDate.setBounds(16, 36, 65, 20);
		// cmbDate.setModel(new DefaultComboBoxModel(new String[] {"Y", "YM",
		// "YMD", "YQ"}));
		DateFormat = (DateDomain) cmbDate.getSelectedItem();
		dialog.getContentPane().add(cmbDate);
		JRadioButton rdbComma = new JRadioButton("Comma");
		rdbComma.setBounds(87, 37, 75, 23);
		rdbComma.setSelected(true);
		FileFormat = "comma";
		rdbComma.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				Gui.this.FileFormat = "comma";
			}

		});
		dialog.getContentPane().add(rdbComma);

		JRadioButton rdbTab = new JRadioButton("Tab");
		rdbTab.setBounds(170, 35, 61, 23);
		rdbTab.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent arg0) {
				Gui.this.FileFormat = "tab";
			}

		});
		dialog.getContentPane().add(rdbTab);
		ButtonGroup group = new ButtonGroup();
		group.add(rdbTab);
		group.add(rdbComma);

		JLabel lblFileFormat = new JLabel("File Delimiter");
		lblFileFormat.setBounds(95, 23, 83, 14);
		dialog.getContentPane().add(lblFileFormat);
		JButton btnDone = new JButton("Done.");
		btnDone.setBounds(0, 70, 80, 25);
		dialog.getContentPane().add(btnDone);
		btnDone.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent arg0) {
				// TODO Auto-generated method stub
				dialog.setVisible(false);
			}

		});

		dialog.setVisible(true);
		DateFormat = (DateDomain) cmbDate.getSelectedItem();

	}
public void runInterpolate(JDialog dialog2, int numNeighbors, float exponent){
	double start = System.currentTimeMillis();
	
	ConcurrentInterpolationSec interpolation = new ConcurrentInterpolationSec(dataSet,locationDataSet,numNeighbors, 
			exponent,locationDataSet.getDataSetFileName()+"-interpolated.txt" );
	
	try
	{
		Thread t = new Thread(interpolation);
		t.start();
		t.join();
		double end = System.currentTimeMillis();
		double duration = (end - start) / 1000;
		System.out.println("Interpolation took " + duration + " seconds.");
		int fromMonthint=0;
		int toMonthint =0;
		
		try{
	 fromMonthint = Integer.parseInt(fromMonth.getText());
	toMonthint = Integer.parseInt(toMonth.getText());
		}catch (Exception e){}
		if (fromMonthint ==0 || toMonthint==0 ||(fromMonthint>toMonthint)){
			fromMonthint=6;
			toMonthint=8;
			fromMonth.setText("6");
			toMonth.setText("8");
		}
		interpolation.writeInterpolationsToFile(fromMonthint, toMonthint);
	}
	catch(Exception ee)
	{
	}
	dialog2.setVisible(false);
}
public void runValidate(JDialog dialog2, int numNeighbors, float exponent){
	LOOCV.statsFilename= dataSet.getDataSetFileName()+"-error-statistics.txt";
	LOOCV l =LOOCV.executeLOOCVInterpolation(dataSet, numNeighbors, exponent);
	try {
		Thread.sleep(1000);
	} catch (InterruptedException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
	lblErrors.setText(l.getErrors().toStringRounded());
	dialog2.setVisible(false);
}
}
